package com.junxonline.instant.terminal.netty;

import com.junxonline.instant.terminal.config.NettyConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetAddress;

/**
 * Netty服务器
 *
 * @author JunX
 * @date 2021-09-03
 */
@Log4j2
@Component
public class NettyServer {

    @Autowired
    private NettyChannelInitializer nettyChannelInitializer;

    @Autowired
    private NettyConfig nettyConfig;

    /**
     * BossGroup线程
     */
    private EventLoopGroup bossGroup;

    /**
     * WorkGroup线程
     */
    private EventLoopGroup workGroup;

    /**
     * 启动Netty
     *
     * @throws Exception Exception
     */
    @PostConstruct
    public void start() throws Exception {
        bossGroup = new NioEventLoopGroup(nettyConfig.getBossGroupCount());
        workGroup = new NioEventLoopGroup(nettyConfig.getWorkGroupCount());
        // 初始化Netty
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap
                .localAddress(nettyConfig.getPort())
                .group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .option(ChannelOption.SO_BACKLOG, 1024)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, nettyConfig.getConnectionTimeoutMs())
                .option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.SO_KEEPALIVE, false)
                .childHandler(nettyChannelInitializer);
        serverBootstrap.bind().sync();
        log.info("- Netty Server started on -> ws://{}:{}{}", InetAddress.getLocalHost().getHostAddress(), nettyConfig.getPort(), nettyConfig.getPath());
    }

    /**
     * 停止Netty
     */
    @PreDestroy
    public void stop() {
        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
        log.info("- Netty Server stopped on port: {}", nettyConfig.getPort());
    }

}
